package com.rf.sys.logAop;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import javax.inject.Inject;

import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.rf.sys.annotation.SystemLog;
import com.rf.sys.dao.SysLogMapper;
import com.rf.sys.model.SysLog;

/**
 * 切点类
 * @author LJN
 * @since 2015-05-05 Pm 20:35
 * @version 1.0
 */
@Aspect
@Component
public  class LogAopAction {
    //本地异常日志记录对象
     private  static  final Logger logger = LoggerFactory.getLogger(LogAopAction. class);
     @Inject
     private SysLogMapper sysLogMapper;
     //Controller层切点
     @Pointcut("@annotation(com.rf.sys.annotation.SystemLog)")
     	public  void controllerAspect() {
     }
    
    /**
     * 操作异常记录
     *@descript
     *@param point
     *@param e
     */
    @AfterThrowing(pointcut = "controllerAspect()", throwing = "e")  
    public  void doAfterThrowing(JoinPoint point, Throwable e) {
		Map<String, Object> map = null;
		String userId = null;
		String ip = null;
		String description = e.toString();
		try {
			ip = SecurityUtils.getSubject().getSession().getHost();
		} catch (Exception ee) {
			description = ",无法获取登录用户Ip";
		}
		try {
			map=getControllerMethodDescription(point);
			// 登录名
			userId = (String) SecurityUtils.getSubject().getSession().getAttribute("userSessionId");
			if (!StringUtils.isNotEmpty(userId)) {
				description = description + ",无法获取登录用户信息！";
			}
		} catch (Exception ee) {
			description = description+",无法获取登录用户信息！";
		}
		SysLog sysLog = new SysLog();
		sysLog.setUserId(userId);
		sysLog.setModule((String)map.get("module"));
		sysLog.setMethods((String)map.get("methods"));
		sysLog.setDescription(e.toString());
		sysLog.setActionTime("0");
		sysLog.setUserIp(ip);
		sysLogMapper.insertSelective(sysLog);
    }
    /**
     * 前置通知 用于拦截Controller层记录用户的操作
     *
     * @param joinPoint 切点
     */
    @Around("controllerAspect()")
    public Object doController(ProceedingJoinPoint point) {
    	Object result = null;
		// 执行方法名
		String methodName = point.getSignature().getName();
		String className = point.getTarget().getClass().getSimpleName();
		Map<String, Object> map = null;
		String userId = null;
		String description = null;
		Long start = 0L;
		Long end = 0L;
		Long time = 0L;
		String ip = null;
		// 当前用户
		try{
			map=getControllerMethodDescription(point);
			// 执行方法所消耗的时间
			start = System.currentTimeMillis();
			result = point.proceed();
			end = System.currentTimeMillis();
			time = end - start;
		}catch(Throwable e) {
			throw new RuntimeException(e);
		}
		description = (String)map.get("description");
		try {
			ip = SecurityUtils.getSubject().getSession().getHost();
		} catch (Exception e) {
			description = description+ ",无法获取登录用户Ip";
		}
		try {
			// 登录名
			userId = (String) SecurityUtils.getSubject().getSession().getAttribute("userSessionId");
			if (!StringUtils.isNotEmpty(userId)) {
				description = description+ ",无法获取登录用户信息！";
			}
		} catch (Exception e) {
			description = description+ ",无法获取登录用户信息！";
		}
		
		SysLog sysLog = new SysLog();
		sysLog.setUserId(userId);
		sysLog.setModule((String)map.get("module"));
		sysLog.setMethods((String)map.get("methods"));
		sysLog.setDescription(description);
		sysLog.setActionTime(time.toString());
		sysLog.setUserIp(ip);
		sysLogMapper.insertSelective(sysLog);
        return result;
    }
    /**
     * 获取注解中对方法的描述信息 用于Controller层注解
     *
     * @param joinPoint 切点
     * @return 方法描述
     * @throws Exception
     */
    @SuppressWarnings("rawtypes")
	public Map<String, Object> getControllerMethodDescription(JoinPoint joinPoint)  throws Exception {
    	Map<String, Object> map = new HashMap<String, Object>();
    	String targetName = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] arguments = joinPoint.getArgs();
        Class targetClass = Class.forName(targetName);
        Method[] methods = targetClass.getMethods();
        for (Method method : methods) {
        	if (method.getName().equals(methodName)) {
        		Class[] clazzs = method.getParameterTypes();
                if (clazzs.length == arguments.length) {
                	map.put("module", method.getAnnotation(SystemLog.class).module());
                	map.put("methods", method.getAnnotation(SystemLog.class).methods());
                	String de = method.getAnnotation(SystemLog.class).description();
                	if(!StringUtils.isNotEmpty(de)){
                		de="执行成功!";
                	}
                	map.put("description", de);
                    break;
                }
            }
        }
        return map;
    }
}
